use std::path::PathBuf;
use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(name = "compt", about = "A tool for comparing")]
pub enum Opt {
    #[structopt(name = "check")]
    Check {
        #[structopt(short = "c", long = "compile-file")]
        compile_file: bool,
        #[structopt(
            short = "d",
            long = "data-path",
            default_value = "data",
            parse(from_os_str)
        )]
        data_path: PathBuf,
        #[structopt(
            short = "p",
            long = "program-path",
            default_value = "program.cpp",
            parse(from_os_str)
        )]
        program_path: PathBuf,
        points_count: usize,
    },
    #[structopt(name = "compare")]
    Compare {
        #[structopt(short = "c", long = "compile-file")]
        compile_file: bool,
        #[structopt(
            short = "d",
            long = "data-path",
            default_value = "data",
            parse(from_os_str)
        )]
        data_path: PathBuf,
        #[structopt(
            short = "a",
            long = "data-cpp-path",
            default_value = "data.cpp",
            parse(from_os_str)
        )]
        data_cpp_path: PathBuf,
        #[structopt(
            short = "o",
            long = "original-path",
            default_value = "original.cpp",
            parse(from_os_str)
        )]
        original_path: PathBuf,
        #[structopt(
            short = "p",
            long = "optimized-path",
            default_value = "optimized.cpp",
            parse(from_os_str)
        )]
        optimized_path: PathBuf,
        points_count: usize,
    },
}

impl Opt {
    // * do nothing
    // * a workaround to lazy_static
    pub fn init(&self) {}
    pub fn get_data_path(&self) -> PathBuf {
        match self {
            Opt::Check {
                compile_file: _,
                data_path,
                program_path: _,
                points_count: _,
            } => data_path.clone(),
            Opt::Compare {
                compile_file: _,
                data_path,
                original_path: _,
                data_cpp_path: _,
                optimized_path: _,
                points_count: _,
            } => data_path.clone(),
        }
    }
    pub fn get_points_count(&self) -> usize {
        match self {
            Opt::Check {
                compile_file: _,
                data_path: _,
                program_path: _,
                points_count,
            } => *points_count,
            Opt::Compare {
                compile_file: _,
                data_cpp_path: _,
                data_path: _,
                original_path: _,
                optimized_path: _,
                points_count,
            } => *points_count,
        }
    }
    pub fn get_program_path(&self) -> PathBuf {
        match self {
            Opt::Check {
                compile_file: _,
                data_path: _,
                program_path,
                points_count: _,
            } => program_path.clone(),
            Opt::Compare {
                compile_file: _,
                data_path: _,
                original_path: _,
                optimized_path: _,
                points_count: _,
                data_cpp_path: _,
            } => unimplemented!(),
        }
    }
    pub fn get_original_path(&self) -> PathBuf {
        match self {
            Opt::Check {
                compile_file: _,
                data_path: _,
                program_path: _,
                points_count: _,
            } => unimplemented!(),
            Opt::Compare {
                compile_file: _,
                data_path: _,
                original_path,
                optimized_path: _,
                data_cpp_path: _,
                points_count: _,
            } => original_path.clone(),
        }
    }
    pub fn get_optimized_path(&self) -> PathBuf {
        match self {
            Opt::Check {
                compile_file: _,
                data_path: _,
                program_path: _,
                points_count: _,
            } => unimplemented!(),
            Opt::Compare {
                compile_file: _,
                data_path: _,
                original_path: _,
                optimized_path,
                data_cpp_path: _,
                points_count: _,
            } => optimized_path.clone(),
        }
    }
    pub fn get_data_cpp_path(&self) -> PathBuf {
        match self {
            Opt::Check {
                compile_file: _,
                data_path: _,
                program_path: _,
                points_count: _,
            } => unimplemented!(),
            Opt::Compare {
                compile_file: _,
                data_path: _,
                original_path: _,
                optimized_path: _,
                data_cpp_path,
                points_count: _,
            } => data_cpp_path.clone(),
        }
    }
    pub fn is_check(&self) -> bool {
        match self {
            Opt::Check {
                compile_file: _,
                data_path: _,
                program_path: _,
                points_count: _,
            } => true,
            Opt::Compare {
                compile_file: _,
                data_path: _,
                original_path: _,
                optimized_path: _,
                points_count: _,
                data_cpp_path: _,
            } => false,
        }
    }
}
